﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace Tibco.ServiceModel
{
    internal abstract class TibcoInputChannelBase : TibcoChannelBase, IInputChannel, IChannel, ICommunicationObject
    {
        private readonly EndpointAddress _localAddress;

        private readonly Func<TimeSpan, Message> _receiveMethod;

        private readonly CommunicationOperation<bool, Message> _tryReceiveMethod;

        private readonly Func<TimeSpan, bool> _waitForMessage;

        public EndpointAddress LocalAddress
        {
            get
            {
                return this._localAddress;
            }
        }

        protected TibcoInputChannelBase(BindingContext context, EndpointAddress localAddress) : base(context)
        {
            this._localAddress = localAddress;
            TibcoInputChannelBase TibcoInputChannelBase = this;
            this._receiveMethod = new Func<TimeSpan, Message>(TibcoInputChannelBase.Receive);
            TibcoInputChannelBase TibcoInputChannelBase1 = this;
            this._tryReceiveMethod = new CommunicationOperation<bool, Message>(TibcoInputChannelBase1.TryReceive);
            TibcoInputChannelBase TibcoInputChannelBase2 = this;
            this._waitForMessage = new Func<TimeSpan, bool>(TibcoInputChannelBase2.WaitForMessage);
        }

        public virtual IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._receiveMethod.BeginInvoke(timeout, callback, state);
        }

        public virtual IAsyncResult BeginReceive(AsyncCallback callback, object state)
        {
            return this._receiveMethod.BeginInvoke(base.Context.Binding.ReceiveTimeout, callback, state);
        }

        public virtual IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
        {
            Message message;
            return this._tryReceiveMethod.BeginInvoke(timeout, out message, callback, state);
        }

        public virtual IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._waitForMessage.BeginInvoke(timeout, callback, state);
        }

        public virtual Message EndReceive(IAsyncResult result)
        {
            return this._receiveMethod.EndInvoke(result);
        }

        public virtual bool EndTryReceive(IAsyncResult result, out Message message)
        {
            return this._tryReceiveMethod.EndInvoke(out message, result);
        }

        public virtual bool EndWaitForMessage(IAsyncResult result)
        {
            return this._waitForMessage.EndInvoke(result);
        }

        public abstract Message Receive(TimeSpan timeout);

        public virtual Message Receive()
        {
            return this.Receive(base.Context.Binding.ReceiveTimeout);
        }

        public abstract bool TryReceive(TimeSpan timeout, out Message message);

        public abstract bool WaitForMessage(TimeSpan timeout);
    }
}